﻿using System.Collections.Generic;
using FluentNHibernate.Automapping;
using FluentNHibernate.Cfg;
using FluentNHibernate.Cfg.Db;
using Insesoft.Entities.Mappings.Fluent;
using Insesoft.Entities.Repository;
using NHibernate;
using NHibernate.Cfg;

namespace Insesoft.Entities.Repositories
{
    public abstract class BaseRepository
    {
        #region Declarations

        private Configuration configuration;
        private static readonly IDictionary<string, ISessionFactory> sessionFactoryPerConnection = new Dictionary<string, ISessionFactory>();
        
        #endregion
        
        #region Properties: Public
        
        private ISessionFactory SessionFactory
        {
            get
            {
                var connectionString = Configuration.GetProperty(Environment.ConnectionString);
                if (!sessionFactoryPerConnection.ContainsKey(connectionString))
                    sessionFactoryPerConnection[connectionString] = Configuration.BuildSessionFactory();
                return sessionFactoryPerConnection[connectionString];
            }
        }

        public Configuration Configuration 
        { 
            get { return configuration ?? (configuration = CreateConfiguration()); }
        }

        #endregion

        #region Methods: Public

        public ISession OpenSession()
        {
            return SessionFactory.OpenSession();
        }

        public void Initialize()
        {
            Configuration.BuildSessionFactory();
        }

        #endregion
        
        #region Methods: Non-Public

        protected virtual Configuration CreateConfiguration()
        {
            return Fluently.Configure()
                 .Database(MsSqlConfiguration.MsSql2008.ConnectionString(c => c.FromConnectionStringWithKey("INSE")))
                //.Mappings(m => m.HbmMappings.AddFromAssemblyOf<EntidadBase>())

                 //.Mappings(m => m.FluentMappings.AddFromAssemblyOf<EntidadBase>()
                //                .Conventions.Add<ForeingKeyNamingConvention>()
                //                .Conventions.Add<ManyToManyTableNamingConvention>())
                 .Mappings(m => m.FluentMappings.Add<OrdenMap>()
                                 .Conventions.Add<ForeingKeyNamingConvention>()
                                 .Conventions.Add<ManyToManyTableNamingConvention>())
                 .Mappings(m => m.AutoMappings.Add(CreateMappings()
                                     .Conventions.Add<ForeingKeyNamingConvention>()
                                     .Conventions.Add<ManyToManyTableNamingConvention>()))
                 .BuildConfiguration();
        }

        protected static AutoPersistenceModel CreateMappings()
        {
            var exclusions = new List<string> { "SolicitudCotizacionReport", "EntidadBase", "Orden" };
            return AutoMap
                .Assemblies()
                .AddMappingsFromAssemblyOf<EntidadBase>()
                .Where(t => t.Namespace == "Insesoft.Entities"
                            && t.IsClass
                            && !exclusions.Contains(t.Name));
        }

        #endregion
    }
}
